package com.chenxin.wms.process.check.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.chenxin.common.annotation.WmsLogs;
import com.chenxin.common.core.domain.AjaxResult;
import com.chenxin.common.enums.*;
import com.chenxin.common.exception.wms.WmsException;
import com.chenxin.wms.domain.*;
import com.chenxin.wms.domain.dto.BatchForbidRequestDTO;
import com.chenxin.wms.domain.dto.TaskRequestDTO;
import com.chenxin.wms.mapper.*;
import com.chenxin.wms.process.check.ICheckProcess;
import com.chenxin.wms.service.ILocationService;
import com.chenxin.wms.service.IWcsTaskService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.util.Date;
import java.util.List;

@Service
@Slf4j
public class CheckProcessImpl implements ICheckProcess {

    @Autowired
    private TaskMapper taskMapper;
    @Autowired
    private StockMapper stockMapper;
    @Autowired
    private LocationMapper locationMapper;
    @Autowired
    private ContainerMapper contMapper;
    @Autowired
    private StationMapper stationMapper;
    @Autowired
    private WarehouseMapper warehouseMapper;
    @Autowired
    private WcsTaskMapper wcsTaskMapper;
    @Autowired
    private ILocationService locationService;

    @Override
    @WmsLogs(name = "盘点任务创建")
    @Transactional(rollbackFor = Exception.class)
    public void stockCheck(BatchForbidRequestDTO request) {
        List<Long> stockIds = request.getIds();
        if (stockIds == null) {
            throw new WmsException("未选择待盘点库存");
        }
        Long userId = request.getUserId();
        Date startDate = new Date();
        String comment = "创建盘点任务";
        String code = "0";
        String msg = comment + "成功";
        String work = "TaskController.stockCheck";

        for (Long stockId : stockIds) {
            //生成盘库任务 proc_wms_stock_check
            StockEntity stockEntity = stockMapper.selectById(stockId);
            if (ObjectUtils.isEmpty(stockEntity)) {
                msg = "库存[" + stockId + "]在表中不存在!请核查";
                throw new WmsException(msg);
            }
            //只有[初始]与[配货中]的单据可进行配货
            String contNo = stockEntity.getContNo();
            if (stockEntity.getStockStatus() != 0 || stockEntity.getLockStatus() != 0) {
                msg = "托盘[" + contNo + "]的库存状态不允许盘点";
                throw new WmsException(msg);
            }
            //托盘不允许存在非盘点出库任务
            List<TaskEntity> taskList = taskMapper.selectList(new QueryWrapper<TaskEntity>()
                    .in("task_status", WmsTaskStatus.INITIAL.getCode(), WmsTaskStatus.PROGRESS.getCode())
                    .ne("task_sub_type", WmsTaskSubType.CHECK_OUT.getCode())
                    .eq("from_cont_no", contNo));
            if (ObjectUtils.isNotEmpty(taskList)) {
                msg = "托盘[" + contNo + "]存在任务！不允许盘点";
                throw new WmsException(msg);
            }
            //只有在实际货位上的库存，才允许库存盘点
            LocationEntity locationEntity = locationMapper.selectOne(new QueryWrapper<LocationEntity>().eq("location_no", stockEntity.getLocationNo()));
            if (WmsLocateType.ST.getCode().equals(locationEntity.getLocationType())) {
                msg = "托盘[" + contNo + "]当前所在位置[" + stockEntity.getLocationNo() + "]不允许盘点";
                throw new WmsException(msg);
            }
            StockEntity updateStock = new StockEntity();
            updateStock.setStockStatus(1);
            updateStock.setStockId(stockId);
            updateStock.setComments(comment);
//        updateStock.setLockedQty(stockEntity.getStockQty());
            updateStock.setUpdater(userId);
            updateStock.setUpdateDate(startDate);
            try {
                stockMapper.updateById(updateStock);
            } catch (Exception e) {
                msg = "托盘[" + contNo + "]的库存修改失败";
//                insertLogWork.setWorkCode(code);
//                insertLogWork.setWorkMsg(e.getMessage());
//                logWorkService.logWorkInsert(insertLogWork);
                throw new WmsException(msg);
            }

            //如果当前库存托盘有盘点出库任务存在，则无需再生成任务
            List<TaskEntity> taskEntities = taskMapper.selectList(new QueryWrapper<TaskEntity>()
                    .eq("task_status", WmsTaskStatus.INITIAL.getCode())
                    .eq("task_sub_type", WmsTaskSubType.CHECK_OUT.getCode())
                    .eq("from_cont_no", contNo));
            if (ObjectUtils.isEmpty(taskEntities)) {
                TaskEntity insertTask = new TaskEntity();
                insertTask.setTaskType(WmsTaskType.CHECK.getCode());
                insertTask.setTaskSubType(WmsTaskSubType.CHECK_OUT.getCode());
                insertTask.setFromContNo(contNo);
                insertTask.setSpuNo(stockEntity.getSpuNo());
                insertTask.setPlanQty(stockEntity.getStockQty());
                insertTask.setActualQty(BigDecimal.ZERO);
                insertTask.setFromPosition(stockEntity.getLocationNo());
                insertTask.setCurPosition(stockEntity.getLocationNo());
                insertTask.setStockId(stockId);
                insertTask.setTaskStatus(WmsTaskStatus.INITIAL.getCode());
                insertTask.setCreator(userId);
                insertTask.setCreateDate(startDate);
                insertTask.setUpdater(userId);
                insertTask.setUpdateDate(startDate);
                insertTask.setComments(comment);
                try {
                    taskMapper.insert(insertTask);
                } catch (WmsException e) {
                    msg = "托盘[" + contNo + "]的任务创建失败";
//                insertLogWork.setWorkCode(code);
//                insertLogWork.setWorkMsg(e.getMessage());
//                logWorkService.logWorkInsert(insertLogWork);
                    throw new WmsException(msg);
                }
            }
        }

        //记录日志
//        insertLogWork.setWorkCode(code);
//        insertLogWork.setWorkMsg(msg);
//        logWorkService.logWorkInsert(insertLogWork);
    }

    @Override
    @WmsLogs(name = "盘点出库执行")
    @Transactional(rollbackFor = Exception.class)
    public void outbound(BatchForbidRequestDTO request) {
//        Long taskId = (Long) params.get("taskId");
        List<Long> ids = request.getIds();
        Long userId = request.getUserId();
        String code = "0";
        String comment = "盘点出库执行";
        String msg = comment + "成功";
        for (Long taskId : ids) {
            TaskEntity taskEntity = taskMapper.selectById(taskId);
            if (ObjectUtils.isEmpty(taskEntity)) {
                msg = "任务[" + taskId + "]不存在!";
                throw new WmsException(msg);
            }
            if (taskEntity.getTaskStatus() > 0) {
                msg = "任务【" + taskId + "】已执行!";
                throw new WmsException(msg);
            }
            //初始化参数
            Date startDate = new Date();
            String work = "TaskController.outbound";
            WarehouseEntity warehouseEntity = warehouseMapper.selectById(taskEntity.getWarehouseId());

            //如果是自动库，就下发设备任务
            if (warehouseEntity.getWarehouseType().equals(WmsWarehouseType.AUTOMATED.getCode())) {
//        根据料箱获取出库站台信息
                ContainerEntity containerEntity = contMapper.selectOne(new QueryWrapper<ContainerEntity>().eq("cont_no", taskEntity.getFromContNo()));
                String dvcNo = containerEntity.getContType();
                //查询站台
                List<StationEntity> stationEntities = stationMapper.selectList(new QueryWrapper<StationEntity>()
                        .eq("dvc_no", dvcNo)
                        .eq("station_type", WmsStationType.SOT.getCode())
                        .eq("is_active", UserStatus.OK.getCode()));
                if (CollectionUtils.isEmpty(stationEntities)) {
                    msg = "当前无可用出库站台!任务[" + taskId + "]!";
                    throw new WmsException(msg);
                }
                StationEntity stationEntity = stationEntities.get(0);
                //修改task状态
                TaskEntity updateTask = new TaskEntity();
                updateTask.setTaskStatus(WmsTaskStatus.PROGRESS.getCode());
                updateTask.setToPosition(stationEntity.getStationNo());
                updateTask.setUpdater(userId);
                updateTask.setUpdateDate(startDate);
                updateTask.setComments(comment);
                taskMapper.update(updateTask, new UpdateWrapper<TaskEntity>()
                        .eq("from_cont_no", taskEntity.getTaskStatus())
                        .eq("task_sub_type", WmsTaskSubType.CHECK_OUT.getCode())
                        .eq("task_status", WmsTaskStatus.INITIAL.getCode()));
                //生成设备任务
                WcsTaskEntity insertPostWcs = new WcsTaskEntity();
                insertPostWcs.setContNo(taskEntity.getFromContNo());
                insertPostWcs.setTrkType(WmsTaskType.CHECK.getCode());
                insertPostWcs.setFrmPos(taskEntity.getFromPosition());
                insertPostWcs.setToPos(stationEntity.getStationNo());
                insertPostWcs.setCurPos(taskEntity.getCurPosition());
                insertPostWcs.setTrkStatus(WmsTaskStatus.INITIAL.getCode());
                insertPostWcs.setCreator(userId);
                insertPostWcs.setCreateDate(startDate);
                insertPostWcs.setUpdater(userId);
                insertPostWcs.setUpdateDate(startDate);
                insertPostWcs.setComments(comment);
                try {
                    wcsTaskMapper.insert(insertPostWcs);
                } catch (Exception e) {
                    msg = "生成设备任务失败!任务[" + taskId + "]!";
//            insertLogWork.setWorkCode(code);
//            insertLogWork.setWorkMsg(e.getMessage());
//            logWorkService.logWorkInsert(insertLogWork);
                    throw new WmsException(msg + e.getMessage());
                }
            } else {
                //修改task状态
                TaskEntity updateTask = new TaskEntity();
                updateTask.setTaskStatus(WmsTaskStatus.PROGRESS.getCode());
                updateTask.setToPosition(taskEntity.getFromPosition());
                updateTask.setUpdater(userId);
                updateTask.setUpdateDate(startDate);
                updateTask.setComments(comment);
                taskMapper.update(updateTask, new UpdateWrapper<TaskEntity>()
                        .eq("from_cont_no", taskEntity.getFromContNo())
                        .eq("task_sub_type", WmsTaskSubType.CHECK_OUT.getCode())
                        .eq("task_status", WmsTaskStatus.INITIAL.getCode()));
            }
        }

        //记录日志
//        insertLogWork.setWorkCode(code);
//        insertLogWork.setWorkMsg(msg);
//        logWorkService.logWorkInsert(insertLogWork);
    }

    @Override
    public void cancel(BatchForbidRequestDTO request) {
        List<Long> taskIds = request.getIds();
        Long userId = request.getUserId();
        Date startDate = new Date();
        String comment = "取消盘点任务";
        String code = "0";
        String msg = comment + "成功";
        String work = "TaskController.cancel";
        /**
         *   1.【完成】状态的盘点任务，不允许取消
         *   2.【执行中】的盘点任务不可取消
         *   3.只要货位的库存还没有下架也可取消
         *   4.搬送指令还是初始状态就允许取消
         */
        for (Long taskId : taskIds) {
            TaskEntity taskEntity = taskMapper.selectById(taskId);
            LocationEntity locationEntity = locationMapper.selectOne(new QueryWrapper<LocationEntity>().eq("location_no", taskEntity.getCurPosition()));
            if (taskEntity.getTaskStatus() > 0
                    || !locationEntity.getLocationType().equals(WmsLocateType.HW.getCode())) {
                msg = "任务[" + taskId + "]无法取消！";
                throw new WmsException(msg);
            }

            //取消盘点时需将库存的预分配状态清掉
            QueryWrapper<StockEntity> queryWrapper = new QueryWrapper<>();
            queryWrapper.lambda().eq(StockEntity::getLocationNo, taskEntity.getFromPosition());
            List<StockEntity> stockEntities = stockMapper.selectList(queryWrapper);
            for (StockEntity stockEntity : stockEntities) {
                if (ObjectUtils.isNotEmpty(stockEntity)) {
                    stockEntity.setStockStatus(0);
                    stockEntity.setUpdateDate(new Date());
                    stockMapper.updateById(stockEntity);
                }
            }
            TaskEntity updateTask = new TaskEntity();
            updateTask.setTaskId(taskId);
            updateTask.setTaskStatus(WmsTaskStatus.CANCEL.getCode());
            updateTask.setUpdater(userId);
            updateTask.setUpdateDate(startDate);
            updateTask.setComments(comment);
            taskMapper.updateById(updateTask);
        }
        //记录日志
//        insertLogWork.setWorkCode(code);
//        insertLogWork.setWorkMsg(msg);
//        logWorkService.logWorkInsert(insertLogWork);
    }

    @Override
    @WmsLogs(name = "盘点确认")
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public AjaxResult checkAffirm(TaskRequestDTO request) {
        Long taskId = request.getTaskId();
        Integer actlQty = request.getActlQty();
        Long userId = request.getUserId();
        Date startDate = new Date();
        String comment = "盘点确认";
        String code = "0";
        String msg = comment + "成功";
        String work = "TaskServiceImpl.checkAffirm";
//        LogWorkEntity insertLogWork = new LogWorkEntity();
//        insertLogWork.setWorkName(comment);
////        insertLogWork.setRelateNo(detailId.toString());
//        insertLogWork.setWorkProc(work);
//        insertLogWork.setCreator(userId);
//        insertLogWork.setCreateDate(startDate);

        TaskEntity taskEntity = taskMapper.selectById(taskId);
        if (ObjectUtils.isEmpty(taskEntity) || taskEntity.getTaskStatus() != 1) {
            msg = "任务[" + taskId + "]不存在或已盘点完成！";
            throw new WmsException(msg);
        }
        if (!WmsTaskSubType.CHECK_OUT.getCode().equals(taskEntity.getTaskSubType())) {
            msg = "任务[" + taskId + "]非盘点任务!不可对其盘点";
            throw new WmsException(msg);
        }
        Long stockId = taskEntity.getStockId();
        StockEntity stockEntity = stockMapper.selectById(stockId);
        if (ObjectUtils.isEmpty(stockEntity)) {
            msg = "库存[" + stockId + "]不存在或无法操作！";
            throw new WmsException(msg);
        }
        String curPosition = stockEntity.getLocationNo();
        LocationEntity locationEntity = locationMapper.selectOne(new QueryWrapper<LocationEntity>().eq("locate_no", curPosition));
        if (ObjectUtils.isEmpty(locationEntity) || !"0".equals(locationEntity.getLocationType())) {
            msg = "托盘[" + taskEntity.getFromContNo() + "]尚未到达出库站台!请等待";
            throw new WmsException(msg);
        }
        ContainerEntity containerEntity = contMapper.selectOne(new QueryWrapper<ContainerEntity>().eq("cont_no", taskEntity.getFromContNo()));
//        if (ObjectUtils.isEmpty(containerEntity) || !"0".equals(containerEntity.getContStatus())) {
//            throw new WmsException("托盘不存在或者不可用!");
//        }
//        根据到达的站台就可知其对应设备
        String dvcNo = locationEntity.getDvcNo();
        //修改task
        TaskEntity updateTask = new TaskEntity();
        updateTask.setTaskId(taskId);
        updateTask.setActualQty(new BigDecimal(actlQty));
        updateTask.setTaskStatus(WmsTaskStatus.COMPLETE.getCode());
        updateTask.setUpdater(userId);
        updateTask.setUpdateDate(startDate);
        updateTask.setComments(comment);
        try {
            taskMapper.updateById(updateTask);
        } catch (Exception e) {
            log.info("修改任务失败", e);
            code = "1001";
            msg = e.getMessage();
//            insertLogWork.setWorkCode(code);
//            insertLogWork.setWorkMsg(msg);
//            logWorkService.logWorkInsert(insertLogWork);
            throw new WmsException("修改任务失败！");
        }
        //库存修正
        StockEntity updateStock = new StockEntity();
        String contNo = stockEntity.getContNo();
        //如果盘点库存剩余数量为 0的话，那么就直接删掉
        if (actlQty == 0) {
            taskMapper.deleteById(stockId);
            //如果库存不存在，那么就不生成回库任务直接返回
            List<StockEntity> stockEntities = stockMapper.selectList(new QueryWrapper<StockEntity>().eq("cont_no", contNo));
            if (ObjectUtils.isEmpty(stockEntities)) {
                return AjaxResult.success("盘点确认成功!此料箱库存已清空，请执行空托盘入库！");
            }
        } else {
            updateStock.setStockId(stockId);
            updateStock.setStockQty(new BigDecimal(actlQty));
            updateStock.setLockedQty(BigDecimal.ZERO);
            updateStock.setUpdater(userId);
            updateStock.setUpdateDate(startDate);
            updateStock.setComments("原库存数量" + stockEntity.getStockQty() + "盘点确认库存" + actlQty);
            try {
                stockMapper.updateById(updateStock);
            } catch (Exception e) {
                log.info("修改库存失败", e);
                code = "1001";
                msg = e.getMessage();
//                insertLogWork.setWorkCode(code);
//                insertLogWork.setWorkMsg(msg);
//                logWorkService.logWorkInsert(insertLogWork);
                throw new WmsException("修改任务失败！");
            }
        }

//        根据设备编号及站台类型（IN）匹配盘点回库的入库站台
        StationEntity stationEntity = stationMapper.selectOne(new QueryWrapper<StationEntity>()
                .eq("dvc_no", dvcNo)
                .eq("station_type", WmsStationType.SIN.getCode()));
        //任务全部执行完成，开始占用货位，生成任务和设备任务
        List<TaskEntity> taskEntityList = taskMapper.selectList(new QueryWrapper<TaskEntity>()
                .eq("cont_no", contNo)
                .eq("task_sub_type", WmsTaskSubType.CHECK_IN.getCode())
                .eq("task_status", WmsTaskStatus.PROGRESS.getCode()));
        if (CollectionUtils.isEmpty(taskEntityList)) {
            LocationEntity preAllocation;
            try {
                preAllocation = locationService.selectToLocationByZoneId(containerEntity.getZoneId());
                //锁定库位
                UpdateWrapper<LocationEntity> updateWrapper = new UpdateWrapper<>();
                updateWrapper.lambda().eq(LocationEntity::getLocationId, preAllocation.getLocationId())
                        .eq(LocationEntity::getLocationStatus, WmsLocateStatus.FREE.getCode())
                        .set(LocationEntity::getLocationStatus, WmsLocateStatus.PRE.getCode())
                        .set(LocationEntity::getContNo, contNo)
                        .set(LocationEntity::getComments, comment)
                        .set(LocationEntity::getUpdater, userId)
                        .set(LocationEntity::getUpdateDate, startDate);
                int locateUpdateNum = locationMapper.update(updateWrapper);
                if (locateUpdateNum <= 0) {
                    throw new WmsException("货位预占用失败！");
                }
            } catch (Exception e) {
                log.info("货位预占用失败", e);
                code = "1001";
                msg = e.getMessage();
//                insertLogWork.setWorkCode(code);
//                insertLogWork.setWorkMsg(msg);
//                logWorkService.logWorkInsert(insertLogWork);
                throw new WmsException("货位预占用失败！");
            }
            //生成任务
            TaskEntity insertTask = new TaskEntity();
            insertTask.setTaskType(WmsTaskType.CHECK.getCode());
            insertTask.setTaskSubType(WmsTaskSubType.CHECK_IN.getCode());
            insertTask.setTaskStatus(WmsTaskStatus.PROGRESS.getCode());
            insertTask.setFromContNo(stockEntity.getContNo());
//            从回库站台进行盘点回库
            insertTask.setFromPosition(stationEntity.getStationNo());
            insertTask.setCurPosition(stationEntity.getStationNo());
            insertTask.setToPosition(preAllocation.getLocationNo());
//            关联库存
            insertTask.setStockId(stockId);
            insertTask.setSpuNo(stockEntity.getSpuNo());
            insertTask.setPlanQty(new BigDecimal(actlQty));
            insertTask.setActualQty(new BigDecimal(actlQty));
            insertTask.setComments(comment);
            insertTask.setCreator(userId);
            insertTask.setCreateDate(startDate);
            insertTask.setUpdater(userId);
            insertTask.setUpdateDate(startDate);
            try {
                taskMapper.insert(insertTask);
            } catch (Exception e) {
                log.info("生成任务失败", e);
                code = "1001";
                msg = e.getMessage();
//                insertLogWork.setWorkCode(code);
//                insertLogWork.setWorkMsg(msg);
//                logWorkService.logWorkInsert(insertLogWork);
                throw new WmsException("生成任务失败！");
            }
            //生成搬送任务
            WcsTaskEntity insertPostWcs = new WcsTaskEntity();
            insertPostWcs.setContNo(contNo);
            insertPostWcs.setTrkType(WmsTaskType.CHECK.getCode());
            insertPostWcs.setFrmPos(stationEntity.getStationNo());
            insertPostWcs.setCurPos(stationEntity.getStationNo());
//            insertPostWcs.setToPos(preAllocation.getLocationNo());
            insertPostWcs.setTrkStatus(WmsTaskStatus.INITIAL.getCode());
            insertPostWcs.setCreator(userId);
            insertPostWcs.setCreateDate(startDate);
            insertPostWcs.setUpdater(userId);
            insertPostWcs.setUpdateDate(startDate);
            insertPostWcs.setComments(comment);
            wcsTaskMapper.insert(insertPostWcs);
        }
        //记录日志
        msg = "盘点确认成功!实物数量[" + request.getActlQty() + "]";
//        insertLogWork.setWorkCode(code);
//        insertLogWork.setWorkMsg(msg);
//        logWorkService.logWorkInsert(insertLogWork);
        return AjaxResult.success(msg);
    }
}
